package cn.gx.kevin.config;

import cn.gx.kevin.common.utils.SysConfigParams;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.redisson.config.ReadMode;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

@Configuration
@ConditionalOnClass({Redisson.class})
@ConditionalOnExpression("'${redis.mode}'=='single' or '${redis.mode}'=='cluster' or '${redis.mode}'=='sentinel'")
public class RedissonClientConfiguration {

    @Autowired
    private Environment environment;

    /**
     * 单机模式 redisson 客户端
     * */
    @Bean
    @ConditionalOnProperty(name = "redis.mode", havingValue = "single")
    RedissonClient redissonSingle() {
        Config config = new Config();
        String node = environment.getProperty("redis.addr");
        String passWord =  environment.getProperty("redis.password");
        String timeout = environment.getProperty("redis.timeout");
        String connTimeout = environment.getProperty("redis.connect.timeout");
        String poolsize = environment.getProperty("redis.poolsize");
        String minIdel =  environment.getProperty("redis.minIdel");

        node = node.startsWith("redis://") ? node : "redis://" + node;
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress(node)
                .setConnectTimeout(StringUtils.isNotEmpty(connTimeout) ? Integer.valueOf(connTimeout) : 10000 )
                .setTimeout(StringUtils.isNotEmpty(timeout) ? Integer.valueOf(timeout) : 10000)
                .setConnectionPoolSize(StringUtils.isNotEmpty(poolsize) ? Integer.valueOf(poolsize) : 64)
                .setConnectionMinimumIdleSize(StringUtils.isNotEmpty(minIdel) ? Integer.valueOf(minIdel) : 2);
        if (StringUtils.isNotBlank(passWord)) {
            serverConfig.setPassword(passWord);
        }
        RedissonClient client = Redisson.create(config);
        return client;
    }

    /**
     * 集群模式的 redisson 客户端
     *
     * @return
     */
    @Bean
    @ConditionalOnProperty(name = "redis.mode", havingValue = "cluster")
    RedissonClient redissonCluster() {
        Config config = new Config();
        String[] nodes =  environment.getProperty("redis.cluster.nodes").split(";");
        for(int i =0 ; i < nodes.length ;i++){
            nodes[i] = nodes[i].startsWith("redis://") ?  nodes[i] : "redis://"+ nodes[i];
        }
        String password =  environment.getProperty("redis.password");
        String timeout =   environment.getProperty("redis.timeout");
        String connTimeout =  environment.getProperty("redis.connect.timeout");

        String scanIvt =  environment.getProperty("redis.cluster.scan-interval");
        String soTimeout =  environment.getProperty("redis.so-timeout");
        String retryAttempts =  environment.getProperty("redis.cluster.retry-attempts");
        String retryInterval =  environment.getProperty("redis.cluster.retry-interval");
        String masterPoolSize =   environment.getProperty("redis.cluster.master-connection-pool-size");
        String slavePoolSize =  environment.getProperty("redis.cluster.slave-connection-pool-size");

        config.setCodec(new org.redisson.client.codec.StringCodec());
        ClusterServersConfig serverConfig = config.useClusterServers().addNodeAddress(nodes)
                .setScanInterval(StringUtils.isEmpty(scanIvt) ? 5000 : Integer.valueOf(scanIvt))
                .setIdleConnectionTimeout(StringUtils.isEmpty(soTimeout) ? 6000 : Integer.valueOf(soTimeout))
                .setConnectTimeout(StringUtils.isEmpty(connTimeout) ? 10000 : Integer.valueOf(connTimeout))
                .setRetryAttempts(StringUtils.isEmpty(retryAttempts) ? 5 : Integer.valueOf(retryAttempts))
                .setRetryInterval(StringUtils.isEmpty(retryInterval) ? 5000 : Integer.valueOf(retryInterval))
                .setMasterConnectionPoolSize(StringUtils.isEmpty(masterPoolSize) ? 64 : Integer.valueOf(masterPoolSize))
                .setSlaveConnectionPoolSize(StringUtils.isEmpty(slavePoolSize) ? 64 : Integer.valueOf(slavePoolSize))
                .setTimeout(StringUtils.isEmpty(timeout) ? 10000 : Integer.valueOf(timeout))
                .setPingConnectionInterval(5000)
                .setReadMode(ReadMode.MASTER_SLAVE);
        if(StringUtils.isNotBlank(password)) {
            serverConfig.setPassword(password);
        }
        RedissonClient client = Redisson.create(config);
        return client;
    }

    /**
     * 哨兵模式 redisson 客户端
     * @return
     */

    @Bean
    @ConditionalOnProperty(name = "spring.redis.mode", havingValue = "sentinel")
    RedissonClient redissonSentinel() {
        Config config = new Config();
//        String[] nodes = redisProperties.getSentinel().getNodes().split(",");
//        List<String> newNodes = new ArrayList(nodes.length);
//        Arrays.stream(nodes).forEach((index) -> newNodes.add(
//                index.startsWith("redis://") ? index : "redis://" + index));
//
//        SentinelServersConfig serverConfig = config.useSentinelServers()
//                .addSentinelAddress(newNodes.toArray(new String[0]))
//                .setMasterName(redisProperties.getSentinel().getMaster())
//                .setReadMode(ReadMode.SLAVE)
//                .setFailedAttempts(redisProperties.getSentinel().getFailMax())
//                .setTimeout(redisProperties.getTimeout())
//                .setMasterConnectionPoolSize(redisProperties.getPool().getSize())
//                .setSlaveConnectionPoolSize(redisProperties.getPool().getSize());
//
//        if (StringUtils.isNotBlank(redisProperties.getPassword())) {
//            serverConfig.setPassword(redisProperties.getPassword());
//        }

        return Redisson.create(config);
    }

}
